//===============================================================================
//
// IncludedTableCollection
//
// PURPOSE: 
// 
//
// NOTES: 
// 
//
//===============================================================================
//
// Copyright (C) 2003 Wallis Software Solutions
// All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR
// FITNESS FOR A PARTICULAR PURPOSE.
//
//===============================================================================

using System.Data;
using Agile.Common;
using Agile.Genie.Descriptors;
using GeneratorCustomization;

namespace Descriptors.GeneratorCustomization
{
    /// <summary>
    /// IncludedTableCollection
    /// </summary>
    public class IncludedTableCollection : AgileCollection
    {
        #region Preserved Region - Developer Hand Written Code

        private static IncludedTableCollection _allIncludedTables;

        /// <summary>
        /// Gets ALL of the columns listed in the excluded columns table.
        /// </summary>
        public static IncludedTableCollection All
        {
            get
            {
                if (_allIncludedTables == null)
                    LoadIncludedTables();
                return _allIncludedTables;
            }
        }

        /// <summary>
        /// Load the included table details from the xml file.
        /// </summary>
        private static void LoadIncludedTables()
        {
            _allIncludedTables = Build();
            DataRowCollection rows = GeneratorsData.GetDataRowsFor("IncludedTable");
            foreach (DataRow row in rows)
            {
                string tableName = (row["TableName"].ToString());
                object databaseColumn = row["Database"];
                string database = string.Empty;
                if (databaseColumn != null)
                    database = databaseColumn.ToString();

                IncludedTable includedTable = IncludedTable.Build(tableName, database);
                _allIncludedTables.Add(includedTable);
            }
        }

        /// <summary>
        /// Checks if the given Included Table is in the collection.
        /// </summary>
        /// <param name="tableToLookFor">Table to look for in the collection.</param>
        /// <returns>True if the item is in the collection.</returns>
        public bool Contains(IncludedTable tableToLookFor)
        {
            foreach (IncludedTable includedTable in this)
            {
                // can't just check on the table name because it would be normal for some different database
                // to have the same table names (e.g. Customer) and we want to be able to set 'All' in the included
                // tables list for a specific database too. 
                if (includedTable.Table == tableToLookFor.Table && includedTable.Database == tableToLookFor.Database)
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Checks if the included table collection contains an item where the table name matches
        /// AND database name matches the given table OR the database value is All.
        /// NOT case sensitive!
        /// </summary>
        /// <remarks>Must only be ONE record in the xml file, with 'ALL' as the database name.</remarks>
        /// <param name="table">Table to match details from.</param>
        /// <returns></returns>
        public bool MatchOnDatabaseAndTable(DatabaseTable table)
        {
            // First, look for a database match that also has All for the table name
            foreach (IncludedTable includedTable in this)
            {
                if (includedTable.Database.ToUpper() == table.DatabaseName.ToUpper())
                    if (includedTable.Table.ToUpper() == "ALL")
                        return true;
            }

            // Then match on the table and database
            foreach (IncludedTable includedTable in this)
            {
                if (!MatchOnTable(table))
                    return false;

                if ((includedTable.Database.ToUpper() == table.DatabaseName.ToUpper())
                    || (includedTable.Database.ToUpper() == "ALL"))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Checks if the included table collection contains an item where the table name matches the given table.
        /// NOT case sensitive!
        /// </summary>
        /// <returns>True if the item is in the collection.</returns>
        public bool MatchOnTable(DatabaseTable table)
        {
            foreach (IncludedTable includedTable in this)
            {
                if (includedTable.Table.ToUpper() == table.Name.ToUpper())
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Returns an included table where there is an item where the table name matches
        /// AND database name matches the given table OR the database value is All.
        /// NOT case sensitive!
        /// </summary>
        /// <param name="tableName">table name</param>
        /// <param name="database">database name.</param>
        /// <returns></returns>
        public IncludedTable FindTable(string tableName, string database)
        {
            foreach (IncludedTable includedTable in this)
            {
                if ((includedTable.Table.ToLower() == tableName.ToLower())
                    && ((includedTable.Database.ToLower() == database.ToLower()))
                    || (includedTable.Database.ToUpper() == "ALL"))
                    return includedTable;
            }
            return null;
        }

        #endregion // Preserved Region - Developer Hand Written Code

        #region Constructors and Factories

        /// <summary>
        /// Constructor
        /// </summary>
        internal IncludedTableCollection()
        {
        }

        /// <summary>
        /// Instantiate a new IncludedTableCollection
        /// </summary>
        public static IncludedTableCollection Build()
        {
            return new IncludedTableCollection();
        }

        #endregion

        #region Strongly Typed IList Implementations

        /// <summary>
        /// Returns the IncludedTable that is at the given index in the collection.
        /// </summary>
        public IncludedTable this[int index]
        {
            get { return InnerList[index] as IncludedTable; }
        }

        /// <summary>
        /// Add a new IncludedTable to the collection
        /// </summary>
        /// <param name="includedTable">includedTable to add to the collection.</param>
        public void Add(IncludedTable includedTable)
        {
            if (Contains(includedTable))
            {
                string message =
                    string.Format(
                        "Tried adding [table:{0}; database:{1}] as an IncludedTable to the collection but it is already in it."
                        , includedTable.Table
                        , includedTable.Database);
                throw new AgileCommonException(message);
            }
            List.Add(includedTable);
        }

        /// <summary>
        /// Remove a IncludedTable from the collection
        /// </summary>
        /// <param name="includedTable">includedTable to remove from the collection.</param>
        public void Remove(IncludedTable includedTable)
        {
            InnerList.Remove(includedTable);
        }

        /// <summary>
        /// Searches for the specified IncludedTable and returns the zero-based index
        /// of the first occurrence within the section of the
        /// collection that starts at the
        /// specified index and contains the specified number of elements.
        /// </summary>
        /// <param name="includedTable">includedTable to get the index of from the collection.</param>
        /// <returns>The index of the item in the collection.</returns>
        public int IndexOf(IncludedTable includedTable)
        {
            return InnerList.IndexOf(includedTable);
        }

        /// <summary>
        /// Searches for the specified IncludedTable and returns the zero-based index
        /// of the first occurrence within the section of the
        /// collection that starts at the
        /// specified index and contains the specified number of elements.
        /// </summary>
        /// <param name="includedTable">includedTable to get the index of from the collection.</param>
        /// <param name="startIndex">The zero-based starting index of the search.</param>
        /// <returns>The index of the item in the collection.</returns>
        public int IndexOf(IncludedTable includedTable, int startIndex)
        {
            return InnerList.IndexOf(includedTable, startIndex);
        }

        /// <summary>
        /// Searches for the specified IncludedTable and returns the zero-based index
        /// of the first occurrence within the section of the
        /// collection that starts at the
        /// specified index and contains the specified number of elements.
        /// </summary>
        /// <param name="includedTable">includedTable to get the index of from the collection.</param>
        /// <param name="startIndex">The zero-based starting index of the search.</param>
        /// <param name="count">The number of elements in the section to search.</param>
        /// <returns>The index of the item in the collection.</returns>
        public int IndexOf(IncludedTable includedTable, int startIndex, int count)
        {
            return InnerList.IndexOf(includedTable, startIndex, count);
        }

        /// <summary>
        /// Inserts the IncludedTable into the collection at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index at which value should be inserted.</param>
        /// <param name="includedTable">includedTable to insert into the collection.</param>
        public void Insert(int index, IncludedTable includedTable)
        {
            InnerList.Insert(index, includedTable);
        }

        /// <summary>
        /// Copies a range of elements from the collection of IncludedTable's to a compatible
        /// one-dimensional System.Array, starting at the specified index of the target array.
        /// </summary>
        /// <param name="includedTables">The one-dimensional System.Array that is the destination of the elements copied from the collection. The System.Array must have zero-based indexing.</param>
        /// <param name="index">The zero-based index at which copying begins.</param>
        public void CopyTo(IncludedTable[] includedTables, int index)
        {
            List.CopyTo(includedTables, index);
        }

        #endregion
    }
}